package com.alipay.sofa.award.endpoint.exception;

import com.alibaba.common.lang.StringUtil;
import com.alipay.sofa.award.endpoint.holder.LocaleHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * SofaRestExceptionHandler
 * <p/>
 * Sofa Rest exception handler, it is better for you to define you owner exception handler
 * <p/>
 * Created by yangguanchao on 18/09/03.
 */
@Component
@Provider
public class SofaRestExceptionHandler implements ExceptionMapper<Throwable> {

    private static final Logger logger = LoggerFactory
            .getLogger(SofaRestExceptionHandler.class);

    private static final String ERROR_CODE_KEY = "code";

    private static final String MESSAGES_KEY = "message";

    private static final String ZH = "zh";

    private static final String ZH_CN = "zh-CN";

    private static final int ERROR_STATUS = 451;

    private static String[] ignoreErrorLogCodeArray = {ActivityAwardErrorCodeDescImpl.ACTIVITY_AWARD_NOTHING.getCode()};

    @Override
    public Response toResponse(Throwable ex) {
        String errorCode = "NO Common Error Code!!";
        String message = "";
        boolean isIgnoreErrorLog = false;
        if (ex instanceof CommonException) {
            CommonException casted = (CommonException) ex;
            String castedErrorCode = casted.getErrorCode();
            errorCode = StringUtil.isBlank(castedErrorCode) ? errorCode : castedErrorCode;
            if (isIgnoreErrorLog(errorCode)) {
                isIgnoreErrorLog = true;
            }
            //EN and CN
            Locale locale = LocaleHolder.getLocale();
            if (locale != null
                    && (ZH.equalsIgnoreCase(locale.getLanguage()) || ZH_CN.equalsIgnoreCase(locale
                    .getLanguage()))) {
                //CN
                message = casted.getZhErrorDesc();
            } else {
                //EN
                message = casted.getEnErrorDesc();
            }
        } else {
            errorCode = "NO Common Error Code!!";
            message = MessageFormat.format("Unknown Exception[{0}]", ex.getMessage());
        }
        if (!isIgnoreErrorLog) {
            logger.error("web api error!", ex);
            logger.error("errorCode={}, message={}", errorCode, message);
        }

        Map<String, Object> errorMap = new HashMap<String, Object>();
        errorMap.put("success", false);
        errorMap.put(ERROR_CODE_KEY, errorCode);
        errorMap.put(MESSAGES_KEY, message);
        return Response.status(ERROR_STATUS).type(MediaType.APPLICATION_JSON).entity(errorMap).build();
    }

    private static boolean isIgnoreErrorLog(String errorCode) {
        for (String ignoreStr : ignoreErrorLogCodeArray) {
            if (ignoreStr.equalsIgnoreCase(errorCode)) {
                return true;
            }
        }
        return false;
    }
}
